<!DOCTYPE html>
<html>
  
<head>
  <meta charset="utf-8">
  <meta name="author" content="饿包子" />
  
  
  <title>乾坤微应用的强制性入门 | 饿包子博客</title>

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
    <meta name="keywords" content="毁人不倦," />
  

  
  <meta name="description" content="面试有问微应用，没用过，花了几天的时间，简单的入个门，然后开始刷面试题。话不多bb，直接进入正题，从零开始搭建。">

  
  
    <link rel="icon" href="/blog/images/xian.ico">
    <link rel="apple-touch-icon" href="/blog/images/Logo.png">
  

  
<link rel="stylesheet" href="/blog/css/Awesome.min.css">


  
<link rel="stylesheet" href="/blog/css/index.css">
<link rel="stylesheet" href="/blog/styles/components/highlight/highlight.css">


  
  
<script src="/blog/common/jquery.min.js"></script>

  
    
<script src="/blog/common/Av.min.js"></script>

  

  
    
<script src="/blog/common/MathJax.js"></script>

  

  
    
<script src="/blog/common/Valine.min.js"></script>

  

  

  <script>
  // theme-ad's config script
  // it can be used in every script
  
  window.AD_CONFIG = {
    leancloud: {"appid":"gE1EosDsVgB2slV4E92yPkcG-gzGzoHsz","appkey":"niR787UVTMyJQrR6gmOiJCKe","comment":true,"count":true},
    welcome: {"enable":false,"interval":30},
    start_time: "2018-06-10",
    passwords: ["a621ab606db2a11f63edc576a729843b8269250dc324206871d90635ac5e531c", ],
    is_post: true,
    lock: false,
    author: "饿包子",
    share: {"twitter":false,"facebook":false,"weibo":true,"qq":true,"wechat":false},
    mathjax: true,
    page_type: "",
    root: "/blog/"
  };
</script>

  
<script src="/blog/vendor/sha256.min.js"></script>
<script src="/blog/js/auth.js"></script>
<script src="/blog/js/index.js"></script>
<script src="/blog/vendor/qrcode.min.js"></script>


<meta name="generator" content="Hexo 5.4.2"></head>
  <body>
    <header class="site-header">
  <div class="site-header-brand">
    
      <span class="site-header-brand-title">
        <a href="/blog/">清风逐月</a>
      </span>
    
    
      <span class="site-header-brand-motto"> | 我思故我在</span>
    
  </div>
  <div class="site-header-right">
    <nav class="site-header-navigation">
      
        <a href="/blog/" target="_self">主页</a>
      
        <a href="/blog/archives/" target="_self">归档</a>
      
        <a href="/blog/tags/" target="_self">标签</a>
      
        <a href="/blog/categories/" target="_self">分类</a>
      
        <a href="/blog/categories/%E6%97%A5%E8%AE%B0" target="_self">日记</a>
      
    </nav>
    <div class="site-header-btn">
      
        <a href="https://github.com/lixianbin1/" target="_blank" id="site-github">
          <i class="fa fa-github-alt"></i>
        </a>
      
      <a href="javascript:void(0);" id="site-search">
        <i class="fa fa-search"></i>
      </a>
      <a href="javascript:void(0);" id="site-nav-btn">
        <i class="fa fa-ellipsis-v"></i>
      </a>
    </div>
  </div>
</header>
<nav class="table-content" id="site-nav">
  <div class="table-content-title">
    <span>导航</span>
  </div>
  <div class="table-content-main">
    <ol class="toc">
      
        <li class="toc-item">
          <a href="/blog/" target="_self">
            主页
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/archives/" target="_self">
            归档
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/tags/" target="_self">
            标签
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/categories/" target="_self">
            分类
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/categories/%E6%97%A5%E8%AE%B0" target="_self">
            日记
          </a>
        </li>
      
    </ol>
  </div>
</nav>
<div id="site-process"></div>
    <main>
      
  <div class="passage">
  <div class="passage-meta">
    <span>
      <i class="fa fa-calendar"></i>2022-08-29
    </span>
    
      <span>
        | <a href="/blog/categories/%E6%AF%81%E4%BA%BA%E4%B8%8D%E5%80%A6/"><i class="fa fa-bookmark"></i>毁人不倦</a>
      </span>
    
    
      <span>
        | <i class="fa fa-unlock-alt"></i>UNLOCK
      </span>
    
    <span>
       | <i class="fa fa-calendar"></i>更新时间:2022-8-29 15:21 
    </span>
  </div>
  <h1 class="passage-title">
    乾坤微应用的强制性入门
  </h1>
  
  <article class="passage-article">
    <h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>微应用，简单的将就是因为项目太多，想要集成成一个项目，但是又不能重构，以前我们会使用iframe进行项目的简单嵌套，然后跨域传值。现在就可以使用微应用，同样是项目嵌套，但是不会有各种事件传递的问题等等；</p>
<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>首先，你得有个项目，它是用来被集成的项目；也就是微应用（子应用）；然后你需要有一个包裹它的项目，也就是主应用。当然也可以临时搭建主应用。让我们从主应用开始。我先用Vue项目进行举例。</p>
<h3 id="主应用"><a href="#主应用" class="headerlink" title="主应用"></a>主应用</h3><p>在主应用安装乾坤库，并导入到项目中</p>
<blockquote>
<p>$ npm install qinkun &amp;&amp; yarn add qiankun</p>
</blockquote>
<figure class="highlight js"><figcaption><span>main.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 下面是在入口文件main.js添加的注册微应用的代码，但之前的代码该有都要有，不能删除</span></span><br><span class="line"><span class="keyword">import</span> &#123; registerMicroApps, start &#125; <span class="keyword">from</span> <span class="string">&quot;qiankun&quot;</span>;</span><br><span class="line"><span class="title function_">registerMicroApps</span>([ <span class="comment">// 在主应用中注册子应用</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&quot;vueApp&quot;</span>, <span class="comment">//子应用名称</span></span><br><span class="line">    <span class="attr">entry</span>: <span class="string">&quot;//localhost:8080&quot;</span>, <span class="comment">//子应用启动的地址</span></span><br><span class="line">    <span class="attr">container</span>: <span class="string">&quot;#container&quot;</span>, <span class="comment">// 子应用在主应用的容器名称,不能和子应用div同名称</span></span><br><span class="line">    <span class="attr">activeRule</span>: <span class="string">&quot;/app-vue&quot;</span>, <span class="comment">// 路由地址,注意你的路由模式是hash # 还是history /</span></span><br><span class="line">    <span class="attr">props</span>: &#123;</span><br><span class="line">      <span class="attr">data</span>: <span class="string">&quot;child子应用&quot;</span>,</span><br><span class="line">    &#125;, <span class="comment">//传参</span></span><br><span class="line">  &#125;,</span><br><span class="line"></span><br><span class="line">]);</span><br><span class="line"><span class="title function_">start</span>(); <span class="comment">// 启动</span></span><br></pre></td></tr></table></figure>

<figure class="highlight js"><figcaption><span>router.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">VueRouter</span> <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 临时搭建的空架子主应用，但要尤为注意 mode，主应用子应用不能是不同的路由模式</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">	<span class="attr">mode</span>:<span class="string">&quot;history&quot;</span>,</span><br><span class="line">	<span class="attr">routes</span>:[</span><br><span class="line"></span><br><span class="line">	]</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><figcaption><span>App.vue</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div id=&quot;app&quot;&gt;</span><br><span class="line">    &lt;p&gt; &lt;router-link to=&quot;/&quot;&gt;主页/&lt;/router-link&gt; &lt;/p&gt;</span><br><span class="line">    &lt;p&gt; &lt;router-link to=&quot;/testapp&quot;&gt;子应用test&lt;/router-link&gt; &lt;/p&gt;</span><br><span class="line">    &lt;p&gt; &lt;router-link to=&quot;/app-vue&quot;&gt;子应用app&lt;/router-link&gt; &lt;/p&gt;</span><br><span class="line">    &lt;div id=&quot;container&quot;&gt;&lt;/div&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure>

<p>同时由于不同项目在各资源的调用的时候需要跨域，所以需要在config设置跨域</p>
<figure class="highlight js"><figcaption><span>vue.config.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">transpileDependencies</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">devServer</span>: &#123;</span><br><span class="line">    <span class="attr">port</span>: <span class="number">8083</span>, <span class="comment">//主应用启动端口号，视情况而定</span></span><br><span class="line">    <span class="attr">headers</span>: &#123;</span><br><span class="line">      <span class="string">&quot;Access-Control-Allow-Origin&quot;</span>: <span class="string">&quot;*&quot;</span>, <span class="comment">// 允许跨域访问子应用页面</span></span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>主应用的东西添加完了，那就开始微应用项目的改造了</p>
<h2 id="微应用"><a href="#微应用" class="headerlink" title="微应用"></a>微应用</h2><p>在 <code>src/</code> 目录下添加文件 <code>public-path.js</code>，同时在<code>package.json</code>设置好全局变量；</p>
<figure class="highlight js"><figcaption><span>public-path.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="variable language_">window</span>.<span class="property">__POWERED_BY_QIANKUN__</span>) &#123;</span><br><span class="line">  __webpack_public_path__ = <span class="variable language_">window</span>.<span class="property">__INJECTED_PUBLIC_PATH_BY_QIANKUN__</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight json"><figcaption><span>package.json</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//...</span></span><br><span class="line"><span class="attr">&quot;eslintConfig&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">  <span class="comment">//...</span></span><br><span class="line">  <span class="attr">&quot;globals&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;__webpack_public_path__&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br></pre></td></tr></table></figure>

<p>修改入口文件main.js，同时保证容器ID不与主应用冲突</p>
<figure class="highlight js"><figcaption><span>main.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&quot;vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&quot;./App.vue&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&quot;./router&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./public-path&#x27;</span></span><br><span class="line"> </span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">productionTip</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 修改render函数</span></span><br><span class="line"><span class="keyword">let</span> instance = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">render</span>(<span class="params">props = &#123;&#125;</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123; container &#125; = props;</span><br><span class="line">  instance = <span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">    router,</span><br><span class="line">    <span class="attr">render</span>: <span class="function">(<span class="params">h</span>) =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>),</span><br><span class="line">  &#125;).$mount(container ? container.<span class="title function_">querySelector</span>(<span class="string">&quot;#app-vue&quot;</span>) : <span class="string">&quot;#app-vue&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="comment">// 独立运行时</span></span><br><span class="line"><span class="keyword">if</span> (!<span class="variable language_">window</span>.<span class="property">__POWERED_BY_QIANKUN__</span>) &#123;</span><br><span class="line">  <span class="title function_">render</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 导出 bootstrap、mount、unmount 三个生命周期钩子，以供主应用在适当的时机调用</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * bootstrap 只会在微应用初始化的时候调用一次，下次微应用重新进入时会直接调用 mount 钩子，不会再重复触发 bootstrap。</span></span><br><span class="line"><span class="comment"> * 通常我们可以在这里做一些全局变量的初始化，比如不会在 unmount 阶段被销毁的应用级别的缓存等。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">bootstrap</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;bootstraped&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 应用每次进入都会调用 mount 方法，通常我们在这里触发应用的渲染方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">mount</span>(<span class="params">props</span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;mount&quot;</span>);</span><br><span class="line">  <span class="title function_">render</span>(props);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 应用每次 切出/卸载 会调用的方法，通常在这里我们会卸载微应用的应用实例</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">unmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;unmount&quot;</span>)</span><br><span class="line">  instance.$destroy();</span><br><span class="line">  instance.<span class="property">$el</span>.<span class="property">innerHTML</span> = <span class="string">&quot;&quot;</span>;</span><br><span class="line">  instance = <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  router,</span><br><span class="line">  <span class="attr">render</span>: <span class="function">(<span class="params">h</span>) =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>),</span><br><span class="line">&#125;).$mount(<span class="string">&quot;#app-vue&quot;</span>);</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><figcaption><span>router.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">VueRouter</span> <span class="keyword">from</span> <span class="string">&#x27;vue-router&#x27;</span></span><br><span class="line"><span class="keyword">import</span> index <span class="keyword">from</span> <span class="string">&#x27;./components/index.vue&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">Hello</span> = (<span class="params"></span>)=&gt; <span class="title function_">import</span>(<span class="string">&#x27;./components/Hello.vue&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">VueRouter</span>)</span><br><span class="line"> </span><br><span class="line"><span class="keyword">const</span> routes = [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;/&#x27;</span>,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;index&#x27;</span>,</span><br><span class="line">      <span class="attr">component</span>: index</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">path</span>:<span class="string">&quot;/Hello&quot;</span>,</span><br><span class="line">        <span class="attr">component</span>:<span class="title class_">Hello</span></span><br><span class="line">    &#125;,</span><br><span class="line">]</span><br><span class="line"><span class="comment">// 注意路由的mode，需要和主应用保持一致，同时路由的匹配需要注意</span></span><br><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> <span class="title class_">VueRouter</span>(&#123;</span><br><span class="line">  <span class="comment">// 这里和主应用中注册子应用时的activeRule对应</span></span><br><span class="line">  <span class="attr">base</span>: <span class="variable language_">window</span>.<span class="property">__POWERED_BY_QIANKUN__</span> ? <span class="string">&quot;/app-vue&quot;</span> : <span class="string">&quot;/&quot;</span>, </span><br><span class="line">  <span class="attr">mode</span>: <span class="string">&quot;history&quot;</span>,</span><br><span class="line">  routes,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> router</span><br></pre></td></tr></table></figure>

<p>在<code>vue.config.js</code>中设置微应用跨域</p>
<figure class="highlight js"><figcaption><span>vue.config.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> &#123; name &#125; = <span class="built_in">require</span>(<span class="string">&quot;./package&quot;</span>);</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">transpileDependencies</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">devServer</span>: &#123;</span><br><span class="line">    <span class="attr">port</span>: <span class="number">8080</span>, <span class="comment">//子应用启动端口号，与上文中父应用注册的子应用端口号对应</span></span><br><span class="line">    <span class="attr">headers</span>: &#123;</span><br><span class="line">      <span class="string">&quot;Access-Control-Allow-Origin&quot;</span>: <span class="string">&quot;*&quot;</span>, <span class="comment">//跨域配置</span></span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">configureWebpack</span>: &#123;</span><br><span class="line">    <span class="attr">output</span>: &#123;</span><br><span class="line">      <span class="attr">library</span>: <span class="string">`<span class="subst">$&#123;name&#125;</span>-[name]`</span>,</span><br><span class="line">      <span class="attr">libraryTarget</span>: <span class="string">&quot;umd&quot;</span>, <span class="comment">// 把微应用打包成 umd 库格式</span></span><br><span class="line">      <span class="comment">// jsonpFunction: `webpackJsonp_$&#123;name&#125;`,</span></span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>配置完成后，执行两项目，注意端口，然后访问主应用即可；</p>
<h2 id="API"><a href="#API" class="headerlink" title="API"></a>API</h2><p>简单讲一下我对它们的个人理解</p>
<blockquote>
<p>registerMicroApps(apps,lifeCycles?)</p>
</blockquote>
<p>在主应用中注册微应用的API方法，参数为微应用和全局微应用的的生命周期钩子。</p>
<blockquote>
<p>start(opts?)</p>
</blockquote>
<p>在主应用中启动乾坤的API方法，参数为一些预加载的相关配置，具体可查询官网。</p>
<blockquote>
<p>setDefaultMountApp(appLink)</p>
</blockquote>
<p>设置主应用启动后默认进入的微应用。</p>
<blockquote>
<p>runAfterFirstMounted(effect)</p>
</blockquote>
<p>第一个微应用启动后调用的API，用于开启一些比如监控或者埋点脚本之类的操作</p>
<blockquote>
<p>loadMicroApp(app, configuration?)</p>
</blockquote>
<p>手动加载微应用场景，具体可见官网</p>
<blockquote>
<p>prefetchApps(apps, importEntryOpts?)</p>
</blockquote>
<p>手动加载微应用静态资源，具体可见官网</p>
<blockquote>
<p>addGlobalUncaughtErrorHandler(handler)</p>
</blockquote>
<p>添加全局的未捕获异常处理器，具体可见官网</p>
<blockquote>
<p>removeGlobalUncaughtErrorHandler(handler)</p>
</blockquote>
<p>移除全局的未捕获异常处理器，具体可见官网</p>
<blockquote>
<p>initGlobalState(state)</p>
</blockquote>
<p>定义全局状态，并返回通信方法，建议在主应用使用，微应用通过 props 获取通信方法</p>
<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><h3 id="主应用和微应用之间的通信"><a href="#主应用和微应用之间的通信" class="headerlink" title="主应用和微应用之间的通信"></a>主应用和微应用之间的通信</h3><p>在主应用创建 <code>action.js</code> 文件</p>
<figure class="highlight js"><figcaption><span>action.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; initGlobalState &#125; <span class="keyword">from</span> <span class="string">&quot;qiankun&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化 state 默认值</span></span><br><span class="line"><span class="keyword">const</span> state = &#123;</span><br><span class="line">  <span class="attr">globalToken</span>:<span class="string">&quot;&quot;</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> actions = <span class="title function_">initGlobalState</span>(state);</span><br><span class="line">actions.<span class="title function_">onGlobalStateChange</span>(<span class="function">(<span class="params">state, prev</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// state: 变更后的状态; prev 变更前的状态</span></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(state, prev);</span><br><span class="line">&#125;);</span><br><span class="line">actions.<span class="title function_">setGlobalState</span>(state);</span><br><span class="line">actions.<span class="title function_">offGlobalStateChange</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> &#123;  actions &#125;</span><br></pre></td></tr></table></figure>

<p>同时在需要的地方进行引用</p>
<figure class="highlight js"><figcaption><span>login.vue</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="keyword">import</span> &#123; actions &#125; <span class="keyword">from</span> <span class="string">&quot;@/action&quot;</span>;</span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">actions.<span class="title function_">setGlobalState</span>(&#123;<span class="attr">globalToken</span>: <span class="variable language_">this</span>.<span class="property">Token</span>&#125;);</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><figcaption><span>App.vue</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; actions &#125; <span class="keyword">from</span> <span class="string">&quot;@/micros&quot;</span>;</span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line">mounted () &#123;</span><br><span class="line">  actions.<span class="title function_">onGlobalStateChange</span>(<span class="function"><span class="params">state</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 监听全局状态，子应用更新主应用数据后触发</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(state)</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在微应用根据需求修改main.js</p>
<figure class="highlight js"><figcaption><span>main.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;Vue&#x27;</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">mount</span>(<span class="params">props</span>) &#123;</span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;mount&quot;</span>,props);</span><br><span class="line">  props.<span class="title function_">onGlobalStateChange</span>(<span class="function">(<span class="params">state, prev</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// state: 变更后的状态; prev 变更前的状态</span></span><br><span class="line">    <span class="comment">// 对监听到的数据进行存储操作，比如vuex</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(state, prev);</span><br><span class="line">  &#125;,<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line">  <span class="title class_">Vue</span>.<span class="property">actions</span>=props <span class="comment">//将主应用传递过的通信方法赋值给vue，后面直接调用Vue进行传值</span></span><br><span class="line">  <span class="title function_">render</span>(props);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>同时在需要的地方进行数值修改，主应用会监测数值修改</p>
<figure class="highlight js"><figcaption><span>login.vue</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 子应用修改数值，主应用监听数据</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">actions</span>.<span class="title function_">setGlobalState</span>(&#123;<span class="attr">name</span>:<span class="string">&quot;asdadas&quot;</span>&#125;)</span><br></pre></td></tr></table></figure>

<h3 id="项目部署"><a href="#项目部署" class="headerlink" title="项目部署"></a>项目部署</h3><p>还不确定，先记录一下别人的方案</p>
<figure class="highlight md"><figcaption><span>项目部署目录</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">├── main</span><br><span class="line">│   └── index.html</span><br><span class="line">└── subapp</span><br><span class="line"><span class="code">    ├── sub-react</span></span><br><span class="line"><span class="code">    │   └── index.html</span></span><br><span class="line"><span class="code">    └── sub-vue</span></span><br><span class="line"><span class="code">        └── index.html</span></span><br></pre></td></tr></table></figure>

<figure class="highlight md"><figcaption><span>nginx</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line"><span class="code">    listen       80;</span></span><br><span class="line"><span class="code">    server_name qiankun.fengxianqi.com;</span></span><br><span class="line"><span class="code">    location / &#123;</span></span><br><span class="line"><span class="code">        root   /data/web/qiankun/main;  # 主应用所在的目录</span></span><br><span class="line"><span class="code">        index index.html;</span></span><br><span class="line"><span class="code">        try_files $uri $uri/ /index.html;</span></span><br><span class="line"><span class="code">    &#125;</span></span><br><span class="line"><span class="code">    location /subapp &#123;</span></span><br><span class="line"><span class="code">        alias /data/web/qiankun/subapp;</span></span><br><span class="line"><span class="code">        try_files $uri $uri/ /index.html;</span></span><br><span class="line"><span class="code">    &#125;</span></span><br></pre></td></tr></table></figure>

<h3 id="问题集合"><a href="#问题集合" class="headerlink" title="问题集合"></a>问题集合</h3><h4 id="ElementUi-字体文件-404错误？"><a href="#ElementUi-字体文件-404错误？" class="headerlink" title="ElementUi 字体文件 404错误？"></a>ElementUi 字体文件 404错误？</h4><p>路径加载错误，需要在 Vue.Config.js 里配置</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> port = xxxx; <span class="comment">// xxxx为端口号</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">publicPath</span>:<span class="string">`//localhost:<span class="subst">$&#123;port&#125;</span>`</span>,</span><br><span class="line">  <span class="comment">//......</span></span><br></pre></td></tr></table></figure>

<h4 id="微应用-ElementUI-样式缺失"><a href="#微应用-ElementUI-样式缺失" class="headerlink" title="微应用 ElementUI 样式缺失?"></a>微应用 ElementUI 样式缺失?</h4><p>在不开启严格模式的情况下，在主应用导入ElementUi样式，然后在主应用的第三方库设置Class前缀；如开启严格模式，可能会导致部分微应用样式问题；</p>
  </article>
  <aside class="table-content" id="site-toc">
  <div class="table-content-title">
    <i class="fa fa-arrow-right fa-lg" id="site-toc-hide-btn"></i>
    <span>目录</span>
  </div>
  <div class="table-content-main">
    <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E8%A8%80"><span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C"><span class="toc-text">准备工作</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%BB%E5%BA%94%E7%94%A8"><span class="toc-text">主应用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%BE%AE%E5%BA%94%E7%94%A8"><span class="toc-text">微应用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#API"><span class="toc-text">API</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9C%BA%E6%99%AF"><span class="toc-text">场景</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%BB%E5%BA%94%E7%94%A8%E5%92%8C%E5%BE%AE%E5%BA%94%E7%94%A8%E4%B9%8B%E9%97%B4%E7%9A%84%E9%80%9A%E4%BF%A1"><span class="toc-text">主应用和微应用之间的通信</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E9%83%A8%E7%BD%B2"><span class="toc-text">项目部署</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%97%AE%E9%A2%98%E9%9B%86%E5%90%88"><span class="toc-text">问题集合</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ElementUi-%E5%AD%97%E4%BD%93%E6%96%87%E4%BB%B6-404%E9%94%99%E8%AF%AF%EF%BC%9F"><span class="toc-text">ElementUi 字体文件 404错误？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BE%AE%E5%BA%94%E7%94%A8-ElementUI-%E6%A0%B7%E5%BC%8F%E7%BC%BA%E5%A4%B1"><span class="toc-text">微应用 ElementUI 样式缺失?</span></a></li></ol></li></ol></li></ol>
  </div>
</aside>

  
  
    <aside class="passage-copyright">
      <div>本文作者: 饿包子</div>
      
        <div>
          原文链接: 
          <a href="" target="_blank">https://lixianbin1.github.io/blog/2022/08/29/%E3%80%90%E6%AF%81%E4%BA%BA%E4%B8%8D%E5%80%A6%E3%80%91%E4%B9%BE%E5%9D%A4%E5%BE%AE%E5%BA%94%E7%94%A8%E7%9A%84%E5%BC%BA%E5%88%B6%E6%80%A7%E5%85%A5%E9%97%A8/</a>
        </div>
      
      <div>
        版权声明: 本博客所有文章除特别声明外, 均采用 <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> 许可协议. 转载请注明出处!
      </div>
    </aside>
  
  
</div>

    </main>
    
      
<div class="site-comment-contanier" data-plateform="leancloud">
  
    <p id="site-comment-info">
      <i class="fa fa-spinner fa-spin"></i> 评论加载中
    </p>
    <div id="site-comment"></div>
  
</div>
    
    
<div class="site-footer-wrapper">
<!--
  <div class="footer-top">
    <a class="left" href="/blog/2022/08/29/%E3%80%90%E9%9D%A2%E8%AF%95%E9%9B%86%E9%94%A6%E3%80%91%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9A%84%E6%94%B6%E9%9B%86%E5%92%8C%E6%80%BB%E7%BB%93(%E8%BF%9B%E9%98%B6%E7%AF%87)/" data-enable="true">
      <i class="fa fa-arrow-left"></i>
    </a>
    <a class="right" href="/blog/2022/04/29/%E3%80%90%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%E3%80%91Electronjs%E7%9A%84%E5%85%A5%E9%97%A8%E5%8F%8A%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/" data-enable="true">
      <i class="fa fa-arrow-right"></i>
    </a>
  </div>
-->
  <footer class="site-footer">
    
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">网站推荐</h5>
          
            <span class="site-footer-item">
              <a href="https://tympanus.net/codrops/" target="_blank">Codrops</a>
            </span>
          
            <span class="site-footer-item">
              <a href="http://taobaofed.org/" target="_blank">淘宝前端团队(FED)</a>
            </span>
          
        </div>
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">文档教程</h5>
          
            <span class="site-footer-item">
              <a href="https://es6.ruanyifeng.com/" target="_blank">ES6入门</a>
            </span>
          
            <span class="site-footer-item">
              <a href="https://developer.mozilla.org/zh-CN/docs/Web" target="_blank">MDN Web文档</a>
            </span>
          
        </div>
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">兴趣前沿</h5>
          
            <span class="site-footer-item">
              <a href="https://threejs.org/" target="_blank">threejs</a>
            </span>
          
            <span class="site-footer-item">
              <a href="https://github.com/justadudewhohacks/face-api.js" target="_blank">face-api</a>
            </span>
          
        </div>
      
    
    <div class="site-footer-info">
      <i class="fa fa-clock-o"></i> 本站已稳定运行<span id="site-time"></span>
    </div>
    
      <div class="site-footer-info">
        <i class="fa fa-paw"></i> 您是本站第 <span id="site-count"></span> 位访客
      </div>
    
    
      <div class="site-footer-info">
        <i class="fa fa-at"></i> Email: xianbin.me@qq.com
      </div>
    
<!--     <div class="site-footer-info">
      <i class="fa fa-copyright"></i> 
      2019 <a href="https://github.com/dongyuanxin/theme-ad/" target="_blank">Theme-AD</a>.
      Created by <a href="https://godbmw.com/" target="_blank">GodBMW</a>.
      All rights reserved.
    </div> -->
  </footer>
</div>
    <div id="site-layer" style="display:none;">
  <div class="site-layer-content">
    <div class="site-layer-header">
      <span class="site-layer-header-title" id="site-layer-title"></span>
      <i class="fa fa-close" id="site-layer-close"></i>
    </div>
    <div class="site-layer-body" id="site-layer-container">
      <div class="site-layer-input" id="site-layer-search" style="display: none;">
        <input type="text">
        <i class="fa fa-search"></i>
      </div>
      
        <div class="site-layer-reward" id="site-layer-reward" style="display: none;">
          
            <div>
              <img src="/blog/images/wechat.png" alt="WeChat">
              
                <p>WeChat</p>
              
            </div>
          
            <div>
              <img src="/blog/images/alipay.png" alt="AliPay">
              
                <p>AliPay</p>
              
            </div>
          
        </div>
      
      <div id="site-layer-welcome" style="display:none;"></div>
    </div>
  </div>
</div>
    

<div class="bottom-bar">

  <div class="bottom-bar-left">
<!--
    <a href="/blog/2022/08/29/%E3%80%90%E9%9D%A2%E8%AF%95%E9%9B%86%E9%94%A6%E3%80%91%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9A%84%E6%94%B6%E9%9B%86%E5%92%8C%E6%80%BB%E7%BB%93(%E8%BF%9B%E9%98%B6%E7%AF%87)/" data-enable="true">
      <i class="fa fa-arrow-left"></i>
    </a>
    <a href="/blog/2022/04/29/%E3%80%90%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97%E3%80%91Electronjs%E7%9A%84%E5%85%A5%E9%97%A8%E5%8F%8A%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/" data-enable="true">
      <i class="fa fa-arrow-right"></i>
    </a>
-->
  </div>

  
  
  
  <div class="bottom-bar-right">
    <a href="javascript:void(0);" data-enable="true" id="site-toc-show-btn">
      <i class="fa fa-bars"></i>
    </a>
    
      <a href="#site-comment" data-enable="true">
        <i class="fa fa-commenting"></i>
      </a>
    
    <a href="javascript:void(0);" id="site-toggle-share-btn">
      <i class="fa fa-share-alt"></i>
    </a>
    
    <a href="javascript:void(0);" id="back-top-btn">
      <i class="fa fa-chevron-up"></i>
    </a>
  </div>
</div>
    <div id="share-btn">
  
  
  
    <a id="share-btn-weibo" href="javascript:void(0);" target="_blank">
      <i class="fa fa-weibo"></i>
    </a>
  
  
    <a id="share-btn-qq" href="javascript:void(0);" target="_blank">
      <i class="fa fa-qq"></i>
    </a>
  
  
</div>
    





    
  </body>
</html>